
// *******************************************************************
// * ext-addon.js
// *******************************************************************

if (!Ext.app) {
    Ext.app = new Object();
}

// *******************************************************************
// * app.init() - Autodetect deployment values
// * The app.options object is initially populated with values by the
// * application.  However, we can auto-detect other values and fill
// * them in if they have not been supplied.
// *******************************************************************

// Example: http://localhost/1.0.4/members/app/edit.html?x=1&y=2
//    (a web page)
//    urlFull       = http://localhost/1.0.4/members/app/edit.html?x=1&y=2
//    urlBase       = http://localhost/1.0.4/members/app/edit.html
//    urlParams     = ?x=1&y=2
//    urlDir        = http://localhost/1.0.4/members/app
//    urlFile       = edit.html
//    appName       = edit
//    urlDocRoot    = http://localhost/1.0.4                     (a guess)
//    urlScriptRoot = http://localhost/cgi-bin/1.0.4             (a guess)
//    urlDocDir     = http://localhost/1.0.4/members/app         (same as urlDir)
//    urlScriptDir  = http://localhost/cgi-bin/1.0.4/members/app (add cgi-bin)

// Example: http://localhost/cgi-bin/1.0.4/members/app/edit?x=1&y=2
//    (a cgi program)
//    urlFull       = http://localhost/cgi-bin/1.0.4/members/app/edit?x=1&y=2
//    urlBase       = http://localhost/cgi-bin/1.0.4/members/app/edit
//    urlParams     = ?x=1&y=2
//    urlDir        = http://localhost/cgi-bin/1.0.4/members/app
//    urlFile       = edit.html
//    appName       = edit
//    urlDocRoot    = http://localhost/1.0.4                 (a guess)
//    urlScriptRoot = http://localhost/cgi-bin/1.0.4         (a guess)
//    urlScriptDir  = http://localhost/cgi-bin/1.0.4/members/app (same as urlDir)
//    urlDocDir     = http://localhost/1.0.4/members/app     (remove cgi-bin)

Ext.app.init = function () {
    var appName, urlFull, urlBase, urlDir, urlFile, urlParams;
    var urlDocRoot, urlScriptRoot, urlDocDir, urlScriptDir;
    var pos, pos2;

    // augment the deployment values with values we can autodetect
    // Do some sanity checks
    if (!Ext.app.options) {
        Ext.app.options = new Object();
    }
    var options = Ext.app.options;

    if (!Ext.app.conf) {
        Ext.app.conf = new Object();
    }
    if (!Ext.app.conf.global) {
        Ext.app.conf.global = new Object();
    }

    // if (options.urlDocRoot == null) {
    //     alert("ERROR: options.urlDocRoot not set\nDefine 'var options = { urlDocRoot : 'value' }; in your app deployment values");
    // }
    // if (options.urlScriptRoot == null) {
    //     alert("ERROR: options.urlScriptRoot not set\nDefine 'var options = { urlScriptRoot : 'value' }; in your app deployment values");
    // }
    
    // This parsing is (or should be) 100% JavaScript 1.0 (!) compatible

    urlFull = document.location.href;

    pos = urlFull.lastIndexOf("?");
    if (pos > 0) {
        urlParams = urlFull.substring(pos, urlFull.length);
        urlBase   = urlFull.substring(0, pos);
    }
    else {
        urlParams = "";
        urlBase   = urlFull;
    }
    pos = urlBase.lastIndexOf("/");
    if (pos > 0 && pos < urlBase.length - 1) {
        urlFile   = urlBase.substring(pos+1, urlBase.length);
        urlDir    = urlBase.substring(0, pos);
    }
    else {
        urlFile   = "";
        urlDir    = urlBase;
    }
    pos = urlFile.lastIndexOf(".");
    if (pos > 0) {
        appName   = urlFile.substring(0, pos);
    }
    else if (urlFile) {
        appName   = urlFile;
    }
    else {
        appName   = "main";
    }

    pos = urlDir.lastIndexOf("/cgi-bin/");
    if (pos >= 0) {
        var part1 = urlFull.substring(0, pos);
        var part2 = urlFull.substring(pos+8, urlFull.length);
        urlDocDir = part1 + part2;
        urlScriptDir = urlDir;
    }
    else {   // no "/cgi-bin/"
        urlDocDir = urlDir;
        pos = urlDir.indexOf("http");
        if (pos == 0) {
            pos = urlDir.indexOf("/",9);
            urlScriptDir = urlDir.substring(0,pos) + "/cgi-bin" + urlDir.substring(pos,urlDir.length);
        }
        else {
            urlScriptDir = "/cgi-bin" + urlDir;
        }
    }

    pos = urlDocDir.indexOf("http");
    if (pos == 0) {
        pos = urlDocDir.indexOf("/",9);
        pos2 = urlDocDir.indexOf("/",pos+1);
        urlDocRoot = urlDocDir.substring(0,pos2);
        urlScriptRoot = urlDocDir.substring(0,pos) + "/cgi-bin" + urlDocDir.substring(pos,pos2);

        // alert("urlDocRoot = " + urlDocRoot + "\n" +
        //       "urlScriptRoot = " + urlScriptRoot + "\n" +
        //       "urlDocDir = " + urlDocDir + "\n" +
        //       "urlScriptDir = " + urlScriptDir + "\n" +
        //       "pos = " + pos + "; pos2 = " + pos2);
    }
    else {
        pos = urlDocDir.indexOf("/",1);
        urlDocRoot = urlDocDir.substring(0,pos);
        urlScriptRoot = "/cgi-bin" + urlDocDir.substring(0,pos);
    }

    if (options.urlFull       == null) options.urlFull       = urlFull;
    if (options.urlBase       == null) options.urlBase       = urlBase;
    if (options.urlDir        == null) options.urlDir        = urlDir;
    if (options.urlFile       == null) options.urlFile       = urlFile;
    if (options.urlParams     == null) options.urlParams     = urlParams;
    if (options.urlDocRoot    == null) options.urlDocRoot    = urlDocRoot;
    if (options.urlScriptRoot == null) options.urlScriptRoot = urlScriptRoot;
    if (options.urlDocDir     == null) options.urlDocDir     = urlDocDir;
    if (options.urlScriptDir  == null) options.urlScriptDir  = urlScriptDir;
    if (options.appName       == null) options.appName       = appName;

    // Only during development time would you allow the person
    // at the browser to overwrite your deployment values.
    // To enable this, set options.urlConfigOK = 1.
    // alert("urlConfigOK=" + options.urlConfigOK);
    if (options.urlConfigOK != null && options.urlConfigOK != 0) {
        urlParams = options.urlParams;
        if (urlParams != "") {
            // get rid of leading "?"
            urlParams = urlParams.substring(1,urlParams.length);
        }
        var urlParamAssignment, urlParam, urlParamValue;
        // I might need to do some unescaping here. We'll see.
        while (urlParams != "") {
            pos = urlParams.indexOf("&");
            if (pos > 0) {
                urlParamAssignment = urlParams.substring(0,pos);
                urlParams = urlParams.substring(pos+1,urlParams.length);
            }
            else {
                urlParamAssignment = urlParams;
                urlParams = "";
            }
            pos = urlParamAssignment.indexOf("=");
            if (pos > 0) {
                urlParam = urlParamAssignment.substring(0,pos);
                urlParamValue = urlParamAssignment.substring(pos+1,urlParamAssignment.length);
            }
            else {
                urlParam = urlParamAssignmen;
                urlParamValue = 1;
            }
            options[urlParam] = urlParamValue;
            // alert("urlConfig: " + urlParam + "=" + urlParamValue);
        }
    }

    // These values have wide cross-browser support.
    // They are useful for determining what JavaScript features/bugs are supported.
    //    navigator.userAgent:    Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050317 Firefox/1.0.2
    //    navigator.appCodeName:  Mozilla
    //    navigator.appName:      Netscape
    //    navigator.appVersion:   5.0 (Windows; en-US)
    if (options.userAgent      == null) options.userAgent      = navigator.userAgent;
    if (options.appCodeName    == null) options.appCodeName    = navigator.appCodeName;
    if (options.appName        == null) options.appName        = navigator.appName;
    if (options.appVersion     == null) options.appVersion     = navigator.appVersion;

    // These are (or should be) derived from the above 4 "standard" values
    if (options.browserVersion == null) options.browserVersion = parseInt(navigator.appVersion);
    if (options.lang           == null) options.lang           = 'en';
    if (options.langx          == null) options.langx          = 'en-US';

    // These must have some default value if they are not set already
    if (options.theme          == null) options.theme          = 'js-app';

    Ext.app.context = new Ext.app.Context();
}

Ext.app.Context = function () {
    this.session  = new Object();
    this.cache    = new Object();
    this.cache["SessionObject"] = new Object();
    this.precache = new Object();

    this.service = function (serviceType, serviceName, codedConf) {
        // alert("context.service(" + serviceType + "," + serviceName + "," + codedConf + ")");
        var s;
        if (this.cache[serviceType] != null &&
            this.cache[serviceType][serviceName] != null) {
            s = this.cache[serviceType][serviceName];
        }
        else {
            if (!codedConf && serviceName != "default") {
                //alert("context.service(" + serviceType + "," + serviceName + ") not cached and no codedConf given");
            }
            // get the precache values
            var precacheValues;
            if (this.precache[serviceType] != null) {
                if (this.precache[serviceType][serviceName] != null) {
                    precacheValues = this.precache[serviceType][serviceName];
                }
            }
            // get the serviceConf
            var serviceConf;
            if (appConf[serviceType]) {
                if (appConf[serviceType][serviceName] != null) {
                    serviceConf = appConf[serviceType][serviceName];
                }
            }
            // alert("service(" + serviceType + "," + serviceName + "," + codedConf + ") : conf=" + serviceConf);
            if (!serviceConf && codedConf) {
                serviceConf = codedConf;
            }

            // get the serviceTypeConf
            var serviceTypeName, serviceTypeType, serviceTypeConf;
            if (serviceConf != null) {
                serviceTypeName = serviceConf.serviceType;
            }
            if (serviceTypeName == null) {
                serviceTypeName = "default";
            }
            serviceTypeType = serviceType + "Type";
            if (appConf[serviceTypeType] != null) {
                if (appConf[serviceTypeType][serviceTypeName] != null) {
                    serviceTypeConf = appConf[serviceTypeType][serviceTypeName];
                }
            }

            // get serviceClass
            var serviceClass;
            if (serviceConf != null && serviceConf.serviceClass != null) {
                serviceClass = serviceConf.serviceClass;
            }
            else if (serviceTypeConf != null && serviceTypeConf.serviceClass != null) {
                serviceClass = serviceTypeConf.serviceClass;
            }
            else {
                serviceClass = serviceType;
            }

            // construct an instance of the class
            var serviceConstructor = 'var s = new ' + serviceClass + '();';
            // alert(serviceConstructor);
            eval(serviceConstructor);

            // initialize some standard attributes
            if (precacheValues) {
                this.copyObject(precacheValues, s);
            }
            this.copyObject(serviceConf, s);
            this.copyObject(serviceTypeConf, s);
            s.serviceName  = serviceName;
            s.serviceType  = serviceType;
            s.serviceClass = serviceClass;
            if (this.cache[serviceType] == null) {
                this.cache[serviceType] = new Object();
            }
            this.cache[serviceType][serviceName] = s;

            if (s.initService) {
                s.initService();
            }
            s.init();
        }
        return(s);
    }

    this.repository = function (serviceName,conf) {
        return(this.service("Repository",serviceName,conf));
    }

    this.sessionObject = function (serviceName,conf) {
        return(this.service("SessionObject",serviceName,conf));
    }

    this.valueDomain = function (serviceName,conf) {
        return(this.service("ValueDomain",serviceName,conf));
    }

    this.widget = function (serviceName,conf) {
        return(this.service("SessionObject",serviceName,conf));
    }

    this.getValue = function (serviceName, attrib, valueDefault, setDefault) {
        var s, container, value, pos;
        if (serviceName) {
            if (typeof serviceName == "string") {
                if (!attrib) {
                    pos = serviceName.lastIndexOf("-");
                    if (pos >= 0) {
                        attrib = serviceName.substring(pos+1,serviceName.length);
                        serviceName = serviceName.substring(0,pos);
                    }
                    else {
                        attrib = serviceName;
                        serviceName = "default";
                    }
                }
                s = this.cache["SessionObject"][serviceName];
                if (!s && this.precache["SessionObject"] != null &&
                          this.precache["SessionObject"][serviceName] != null) {
                    s = this.precache["SessionObject"][serviceName];
                }
                if (!s) {
                    return(null);
                }
            }
            else {
                s = serviceName;
            }
            value = s[attrib];
        }
        if (value == null && valueDefault != null) {
            value = valueDefault;
            if (setDefault) s[attrib] = value;
        }
        return(value);
    }

    this.setValue = function (serviceName, attrib, value) {
        var s, container, value, pos;
        var changed = 0;
        if (serviceName) {
            if (typeof serviceName == "string") {
                if (!attrib) {
                    pos = serviceName.lastIndexOf("-");
                    if (pos >= 0) {
                        attrib = serviceName.substring(pos+1,serviceName.length);
                        serviceName = serviceName.substring(0,pos);
                    }
                    else {
                        attrib = serviceName;
                        serviceName = "default";
                    }
                }
                s = this.cache["SessionObject"][serviceName];
                if (!s) {
                    if (this.precache["SessionObject"] == null) {
                        this.precache["SessionObject"] = new Object();
                    }
                    if (this.precache["SessionObject"][serviceName] == null) {
                        this.precache["SessionObject"][serviceName] = new Object();
                    }
                    s = this.precache["SessionObject"][serviceName];
                }
            }
            else {
                s = serviceName;
            }
            if (s[attrib] != value) {
                s[attrib] = value;
                changed = 1;
            }
        }
        return(changed);
    }

    this.getValues = function (serviceName, attrib, valueDefault, setDefault) {
        // alert(this + ".getValue(" + serviceName + ", " + attrib + ", " + valueDefault + ", " + setDefault + ")");
        var value = this.getValue(serviceName, attrib, valueDefault, setDefault);
        if (value == null) {
            value = "";
        }
        return(value.split(","));
    }

    this.setValues = function (serviceName, attrib, values) {
        if (typeof(values) == "Array") {
            return(this.setValue(serviceName, attrib, values.join(",")));
        }
        else {
            return(this.setValue(serviceName, attrib, values));
        }
    }

    this.getDOMValue = function (name) {
        var value;
        var elem = this.getElementByName(name);
        if (elem) {
            var i;
            if (elem.value != null) {
                value = elem.value;
            }
            else if (elem.type == "select-one") {
                value = elem.options[elem.selectedIndex].value;
            }
            else if (elem.type == "select-multiple") {
                for (i = 0; i < elem.options.length; i++) {
                    if (elem.options[i].selected) {
                        if (value == null) { value = elem.options[i].value;   }
                        else               { value += "," + elem.options[i].value; }
                    }
                }
            }
        }
        return(value);
    }

    this.setDOMValue = function (name, value) {
        var elem = this.getElementByName(name);
        // alert("setDOMValue(" + name + "," + value + ") [" + elem + "]");
        var changed = 0;
        if (elem) {
            var i;
            var type = elem.type;
            if (type == null) {
                // do nothing
            }
            else if (type == "select-one") {
                // It seems that IE and DOM1 allow elem.value = value
                // for a "select-one" element, but NS4+ and even Firefox
                // don't seem to allow this.
                if (elem.options[elem.selectedIndex].value != value) {
                    elem.options[elem.selectedIndex].selected = false;
                    for (i = 0; i < elem.options.length; i++) {
                        if (elem.options[i].value == value) {
                            if (elem.options[i].selected != true) {
                                elem.options[i].selected = true;
                                changed = 1;
                            }
                            break;
                        }
                    }
                }
            }
            else if (type == "select-multiple") {
                var values;
                if (value == null) {
                    values = [];
                }
                else {
                    values = value.split(",");
                }
                // set up a hash of the values to be set (comma-sep in "value")
                var valuesToBeSet = new Object();
                for (i = 0; i < values.length; i++) {
                    valuesToBeSet[values[i]] = 1;
                }
                for (i = 0; i < elem.options.length; i++) {
                    if (elem.options[i].selected) {
                        if (! valuesToBeSet[elem.options[i].value]) {
                            elem.options[i].selected = false;
                            changed = 1;
                        }
                    }
                    else {
                        if (valuesToBeSet[elem.options[i].value]) {
                            elem.options[i].selected = true;
                            changed = 1;
                        }
                    }
                }
            }
            else if (type == "hidden" ||
                     type == "text" ||
                     type == "textarea" ||
                     type == "radio" ||
                     type == "checkbox" ||
                     type == "file" ||
                     type == "image" ||
                     type == "password" ||
                     type == "reset" ||
                     type == "submit" ||
                     type == "button") {
                if (elem.value != value) {
                    elem.value = value;
                    changed = 1;
                }
            }
        }
        return(changed);
    }
}

Ext.app.init();

// *******************************************************************
// CLASS: Service
// *******************************************************************
Ext.app.Service = function () {
    this.html = html;
    function html () {
        var html = '[' + this.serviceType + '(' + this.serviceName + ') : ' + this.serviceClass + ']';
        return(html);
    }
    this.write = write;
    function write () {
        document.write(this.html());
    }
    this.init = init;
    function init () {
        // do nothing (available for overriding in a subclass)
    }
}

// *******************************************************************
// CLASS: SessionObject
// *******************************************************************
Ext.app.SessionObject = function () {

    // this.init = init;
    // function init () {
    // }

    this.container   = container;
    function container (serviceName) {
        if (serviceName == null) {
            serviceName = this.serviceName;
        }
        var containerServiceName;
        if (serviceName != "default") {
            var pos = serviceName.lastIndexOf("-");
            if (pos <= 0) {
                containerServiceName = "default";
            }
            else {
                containerServiceName = serviceName.substring(0, pos);
            }
        }
        return(containerServiceName);
    }

    // not sure if anyone needs this. it is provided in parallel to the container() function
    this.containerAttrib   = containerAttrib;
    function containerAttrib (serviceName) {
        if (serviceName == null) {
            serviceName = this.serviceName;
        }
        var containerAttribName;
        if (serviceName != "default") {
            var pos = serviceName.lastIndexOf("-");
            if (pos <= 0) {
                containerAttribName = "serviceName";
            }
            else {
                containerAttribName = serviceName.substring(pos+1, serviceName.length);
            }
        }
        return(containerAttribName);
    }

    // This is a tricky area for compatibility between IE and Firefox, particularly
    // when it comes to arriving at the page via the "Back" button.
    this.initDefaultValue = initDefaultValue;
    function initDefaultValue () {
        var currentValue = context.getValue(this.serviceName);     // get if from the session
        if (currentValue == null) {                                // if not...
            currentValue = context.getDOMValue(this.serviceName);  // try getting from the DOM
            if (currentValue != null) {                            // if so (i.e. "Back" button) ...
                context.setValue(this.serviceName, null, currentValue);  // set it in the session
            }
        }
        if (currentValue == null) {                                // otherwise ...
            if (this["default"] != null) {
                context.setValue(this.serviceName, null, this["default"]);
            }
            else {
                context.setValue(this.serviceName, null, "");
            }
        }
    }

    this.validateCurrentValues = validateCurrentValues;
    function validateCurrentValues () {
        var values, validatedValues;
        if (this.controlWidget || this.validate) {
            values = context.getValue(this.serviceName);  // get as a single string
            validatedValues = this.validateValues(values);
            this.setCurrentValue(validatedValues);  // set as a single string
        }
    }

    this.validateValues = validateValues;
    function validateValues (values) {
        var initialValues;
        var i, value, validValues, valueIsValid, validationPattern;
        var possibleValues, wantarray;
        possibleValues = this.getValues();
        // alert(this.serviceName + ".validateValues(" + values + ") : [" + typeof(values) + "]");
        if (typeof(values) == "Array") {
            initialValues = values;
            wantarray = 1;
        }
        else if (possibleValues != null) {
            if (values == "") {
                initialValues = [];
            }
            else {
                initialValues = values.split(",");
            }
            wantarray = 0;
        }
        else {
            initialValues = new Array();
            initialValues[0] = values;
            wantarray = 0;
        }
        // begin keeping a list of the *valid* values
        validValues = new Array();
        // they might be validated by an enumerated list...
        if (possibleValues && possibleValues.length > 0) {
            // make a set of the valid values
            valueIsValid = new Object();
            for (i = 0; i < possibleValues.length; i++) {
                valueIsValid[possibleValues[i]] = 1;
            }
            // check each possible value for inclusion in the set
            for (i = 0; i < initialValues.length; i++) {
                if (valueIsValid[initialValues[i]]) {
                    validValues.push(initialValues[i]);
                    // alert(this.serviceName + ".validateValues() : " + initialValues[i] + " is valid");
                }
            }
            // alert(this.serviceName + ".validateValues() : valid.len=" + validValues.length + " possible.len=" + possibleValues.length);
            if (validValues.length == 0 && ! this.nullable && possibleValues.length > 0) {
                validValues[0] = possibleValues[0];
                // alert(this.serviceName + ".validateValues() : setting value=" + validValues[0]);
            }
        }
        // they might be validated by a regular expression ...
        else if (this.validate) {
            validationPattern = this.validate;
            validValues = new Array();
            for (v = 0; v < initialValues.length; v++) {
                value = initialValues[v];
                if (value.match(validationPattern) != null) {
                    validValues.push(value);
                }
            }
            if (validValues.length == 0 && ! this.nullable && this["default"]) {
                validValues[0] = this["default"];
            }
        }
        else {
            validValues = initialValues;
            if (validValues.length == 0 && ! this.nullable && this["default"]) {
                validValues[0] = this["default"];
            }
        }
        if (wantarray) {
            return(validValues);
        }
        else {
            return(validValues.join(","));
        }
    }

    this.getCurrentValue = getCurrentValue;
    function getCurrentValue () {
        return(context.getValue(this.serviceName));
    }

    this.setCurrentValue = setCurrentValue;
    function setCurrentValue (value) {
        if (this.validate) {
            value = this.validateValues(value);
        }
        var changed = context.setValue(this.serviceName, null, value);
        return(changed);
    }

    this.getCurrentValues = getCurrentValues;
    function getCurrentValues () {
        var value = this.getCurrentValue();
        if (value == null || value == "") {
            return(new Array());
        }
        else {
            return(value.split(","));
        }
    }

    this.setCurrentValues = setCurrentValues;
    function setCurrentValues (values) {
        this.setCurrentValue(values.join(","));
    }

    this.getValues = getValues;
    function getValues () {
        var values = this.values;
        var controlValue, controlValueOptions;
        if (values == null && this.domain) {
            var domain = context.service("ValueDomain", this.domain);
            values = domain.getValues();
        }
        if (values == null && this.controlWidget && this.controlValueOptions) {
            controlValueOptions = this.controlValueOptions;
            controlValue = context.getValue(this.controlWidget);
            if (controlValueOptions[controlValue] && controlValueOptions[controlValue].values) {
                values = controlValueOptions[controlValue].values;
            }
            else if (controlValueOptions["default"] && controlValueOptions["default"].values) {
                values = controlValueOptions["default"].values;
            }
            else {
                values = this.values;
            }
        }
        if (values == null) {
            values = new Array();
        }
        return(values);
    }

    this.getLabels = getLabels;
    function getLabels () {
        var labels = this.labels;
        var controlValue, controlValueOptions;
        if (labels == null && this.domain) {
            var domain = context.service("ValueDomain", this.domain);
            labels = domain.getLabels();
        }
        if (labels == null && this.controlWidget && this.controlValueOptions) {
            controlValueOptions = this.controlValueOptions;
            controlValue = context.getValue(this.controlWidget);
            if (controlValueOptions[controlValue] && controlValueOptions[controlValue].labels) {
                labels = controlValueOptions[controlValue].labels;
            }
            else if (controlValueOptions["default"] && controlValueOptions["default"].labels) {
                labels = controlValueOptions["default"].labels;
            }
            else {
                labels = this.labels;
            }
        }
        if (labels == null) {
            labels = new Object();
        }
        return(labels);
    }

    this.handleEvent = handleEvent;
    function handleEvent (thisServiceName, eventServiceName, eventName, eventArgs) {
        var containerServiceName = this.container(thisServiceName);
        var argString;
        if (eventArgs == null) {
            argString = "null";
        }
        else {
            var i;
            argString = "";
            for (i = 0; i < eventArgs.length; i++) {
                argString += (i == 0) ? "[" : ",";
                argString += eventArgs[i];
            }
            argString += "]";
        }
        var handled;
        if (containerServiceName) {
            var s = context.service("SessionObject", containerServiceName);
            handled = s.handleEvent(containerServiceName, eventServiceName, eventName, eventArgs);
        }
        else if (eventName == "change") {  // ignore change events that are not otherwise handled
            handled = 1;
        }
        else {
            context.log("handleEvent(" + thisServiceName + "," + eventServiceName + "," +
                eventName + "," + argString + ") : Event not handled\n");
            handled = 0;
        }
        return(handled);
    }

    this.getId = getId;
    function getId (withAttrib) {
        var id = this.serviceName;
        // id.replace(/\./g,"-");
        if (withAttrib != null && withAttrib) {
            id = ' id="' + id + '"';
        }
        return(id);
    }
}
Ext.app.SessionObject.prototype = new Ext.app.Service();

// *******************************************************************
// CLASS: ValueDomain
// *******************************************************************
Ext.app.ValueDomain = function () {

    this.getLabels = getLabels;
    function getLabels () {
        var labels = this.labels;
        if (labels == null) {
            labels = new Object();
        }
        return(labels);
    }

    this.getValues = getValues;
    function getValues () {
        var values = this.values;
        var labels, key;
        if (values == null) {
            values = new Array();
            labels = this.labels;
            if (labels != null) {
                for (key in labels) {
                    values.push(key);
                }
                values.sort();
            }
        }
        return(values);
    }
}
Ext.app.ValueDomain.prototype = new Ext.app.Service();

// *******************************************************************
// CLASS: Repository
// *******************************************************************
Ext.app.Repository = function () {

    this.sort = sort;
    function sort (rows, sortKeys, sortType, sortDir) {
        var sortedRows = rows;
        return(sortedRows);
    }
}
Ext.app.Repository.prototype = new Ext.app.Service();

